package interview;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.ImmutableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import java.util.*;

public class ArraysSort {
    private static final Logger logger = LoggerFactory.getLogger(ArraysSort.class);

    public static void main(String[] args) {
        ArraysSort arraysSort = new ArraysSort();
//        arraysSort.testSort();
//        arraysSort.testBinarySearch();
//        arraysSort.testObjects();
//        arraysSort.testIteratorRemove();
//        arraysSort.testForIRemove();
        arraysSort.testForEachRemove();
    }

    public void testSort() {
        List<SortDTO> list = ImmutableList.of(
                new SortDTO("300"),
                new SortDTO("50"),
                new SortDTO("200"),
                new SortDTO("220")
        );
        // 我们先把数组的大小初始化成 list 的大小，保证能够正确执行 toArray
        SortDTO[] array = new SortDTO[list.size()];
        list.toArray(array);

        System.out.println("排序之前:{} " + JSON.toJSONString(array));
        Arrays.sort(array, Comparator.comparing(SortDTO::getSortTarget));
        System.out.println("排序之后:{} " + JSON.toJSONString(array));
    }

    public void testBinarySearch() {
        List<SortDTO> list = ImmutableList.of(
                new SortDTO("300"),
                new SortDTO("50"),
                new SortDTO("200"),
                new SortDTO("220")
        );

        Iterator<SortDTO> it = list.iterator();
        // 我们先把数组的大小初始化成 list 的大小，保证能够正确执行 toArray
        SortDTO[] array = new SortDTO[list.size()];
        list.toArray(array);

        System.out.println("搜索之前:{} " + JSON.toJSONString(array));
        Arrays.sort(array, Comparator.comparing(SortDTO::getSortTarget));
        System.out.println("先排序,结果为:{} " + JSON.toJSONString(array));

        int index = Arrays.binarySearch(array, new SortDTO("200"), Comparator.comparing(SortDTO::getSortTarget));
        index = Arrays.binarySearch(array, new SortDTO("200"));

        if (index < 0) {
            throw new RuntimeException("没有找到 200");
        }
        System.out.println("搜索结果：{}" + JSON.toJSONString(array[index]));

    }

    public boolean testObjects() {
        List<SortDTO> sortDTOList = new ArrayList<>();
        SortDTO s1 = new SortDTO("300");
        SortDTO s2 = new SortDTO("300");
        boolean result = Objects.equals(s1, s2);
        System.out.println("Objects.equals：{} " + result);
        return result;
    }

    public void testIteratorRemove() {
        List<SortDTO> sortDTOList = new ArrayList<>();
        sortDTOList.add(new SortDTO("100"));
        sortDTOList.add(new SortDTO("200"));
        sortDTOList.add(new SortDTO("300"));
        sortDTOList.add(new SortDTO("400"));
        sortDTOList.add(new SortDTO("500"));
        sortDTOList.add(new SortDTO("600"));
        sortDTOList.add(new SortDTO("700"));
        sortDTOList.add(new SortDTO("800"));

//        List<SortDTO> sortDTOList = ImmutableList.of(
//                new SortDTO("10"),
//                new SortDTO("20"),
//                new SortDTO("30"),
//                new SortDTO("40"),
//                new SortDTO("50"),
//                new SortDTO("60"),
//                new SortDTO("70"),
//                new SortDTO("80")
//        );

        Iterator<SortDTO> it = sortDTOList.iterator();

        while (it.hasNext()){
            SortDTO sortDTO = it.next();
            System.out.println("Objects.equals:{} " + sortDTO.toString());
            System.out.println("Objects size : {} " + sortDTOList.size());
            it.remove();
        }

    }

    public void testForIRemove() {

        List<SortDTO> sList = new ArrayList<>();
        sList.add(new SortDTO("100"));
        sList.add(new SortDTO("200"));
        sList.add(new SortDTO("300"));
        sList.add(new SortDTO("400"));
        sList.add(new SortDTO("500"));
        sList.add(new SortDTO("500"));
        sList.add(new SortDTO("500"));
        sList.add(new SortDTO("500"));
        sList.add(new SortDTO("500"));
        sList.add(new SortDTO("600"));


        System.out.println("forI remove(i) before size : {} " + sList.size());
        for (int i = 0; i < sList.size() ; i++) {
            sList.remove(i);//此种删除方式不会报错,但会造成集合size变化,导致集合遍历不完全,循环后仍有剩余元素
        }
        System.out.println("forI remove(i) end size : {} " + sList.size());
        for (int i = 0; i < sList.size() ; i++) {
            System.out.println(sList.get(i).toString());
        }

        sList.clear();
        System.out.println("forI List clear . ");
        sList.add(new SortDTO("100"));
        sList.add(new SortDTO("200"));
        sList.add(new SortDTO("300"));
        sList.add(new SortDTO("400"));
        sList.add(new SortDTO("500"));
        sList.add(new SortDTO("500"));
        sList.add(new SortDTO("500"));
        sList.add(new SortDTO("500"));
        sList.add(new SortDTO("500"));
        sList.add(new SortDTO("600"));

        System.out.println("forI remove(sortDTO) before size : {} " + sList.size());
        for (int i = 0; i < sList.size() ; i++) {
            SortDTO sortDTO = sList.get(i);
            //此种删除方式不会报错,但会造成集合size变化,导致集合遍历不完全,循环后仍有剩余元素
            if(sortDTO.equals(new SortDTO("500"))){
                sList.remove(new SortDTO("500"));
            }
        }
        System.out.println("forI remove(sortDTO) size : {} " + sList.size());
        for (int i = 0; i < sList.size() ; i++) {
            System.out.println(sList.get(i).toString());
        }

    }
    public void testForEachRemove() {

        List<SortDTO> sList = new ArrayList<>();
        sList.add(new SortDTO("100"));
        sList.add(new SortDTO("200"));
        sList.add(new SortDTO("300"));
        sList.add(new SortDTO("400"));
        sList.add(new SortDTO("500"));
        sList.add(new SortDTO("500"));
        sList.add(new SortDTO("500"));
        sList.add(new SortDTO("500"));
        sList.add(new SortDTO("500"));
        sList.add(new SortDTO("600"));


//        System.out.println("foreach remove(s) before size : {} " + sList.size());
//        for (SortDTO s : sList) {
//            sList.remove(s);//必然造成java.util.ConcurrentModificationException,造成程序崩溃
//        }
//
//        System.out.println("foreach remove(s) end size : {} " + sList.size());
//        for (int i = 0; i < sList.size() ; i++) {
//            System.out.println(sList.get(i).toString());
//        }

        sList.clear();
        System.out.println("forI List clear . ");
        logger.error("forI List clear . With logger");
        sList.add(new SortDTO("100"));
        sList.add(new SortDTO("200"));
        sList.add(new SortDTO("500"));
        sList.add(new SortDTO("300"));
        sList.add(new SortDTO("400"));
        sList.add(new SortDTO("500"));
        sList.add(new SortDTO("600"));

        System.out.println("foreach equals remove(new SortDTO(\"500\")) before size : {} " + sList.size());
//        for (SortDTO s : sList) {
//            //当要删除的元素在集合中存在且重复出现时必然发生java.util.ConcurrentModificationException,造成程序崩溃
//            //当要删除的元素在集合中仅存在一份时,即元素在集合中唯一存在,程序能够正常执行,不报错,且结果正常
//            if(s.equals(new SortDTO("500"))){
//                sList.remove(new SortDTO("500"));
//            }
//        }
        System.out.println("foreach equals remove(new SortDTO(\"500\")) end size : {} " + sList.size());
        for (int i = 0; i < sList.size() ; i++) {
            System.out.println(sList.get(i).toString());
        }

    }


    class SortDTO implements Comparable<SortDTO> {
        private String sortTarget;

        public SortDTO(String sortTarget) {
            this.sortTarget = sortTarget;
        }

        public String getSortTarget() {
            return this.sortTarget;
        }

        @Override
        public int compareTo(SortDTO o) {
            return this.sortTarget.compareTo(o.sortTarget);
        }

        @Override
        public String toString() {
            return "SortDTO : " + this.sortTarget;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            SortDTO sortDTO = (SortDTO) o;
            return sortTarget.equalsIgnoreCase(sortDTO.sortTarget);
        }

        @Override
        public int hashCode() {
            return Objects.hash(sortTarget);
        }
    }
}
